package com.gss.stockLedger.service;

import java.io.FileOutputStream;
import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.ss.usermodel.Workbook;

import com.gss.stockLedger.domain.FIFOReportDTO;
import com.gss.stockLedger.domain.SummaryInv;
import com.gss.stockLedger.domain.SummaryParts;
import com.gss.stockLedger.form.ReportGenerateForm;
import com.gss.stockLedger.util.ApplicationConstants;

import static com.gss.stockLedger.service.FIFOReportGenerationService.*;

public class GenerateExcelThread extends Thread {
	

	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MMM-yyyy");
	SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("ddMMyyyyHHmmss");	
	
	boolean running = true;
	boolean writing;
	final Workbook workbook;
	final ReportGenerateForm reportGenerateForm;
	final Date reportDate;
	Map<String, List<FIFOReportDTO>> partId_data_map;
	
	public GenerateExcelThread(Workbook workbook,ReportGenerateForm form,Date date){
		this.workbook = workbook;
		this.reportGenerateForm = form;
		this.reportDate = date;
		partId_data_map = Collections.synchronizedMap(new HashMap<String, List<FIFOReportDTO>>());
	}

	
	
	public boolean isRunning() {
		return running;
	}

	public boolean isWriting() {
		return writing;
	}

	public void setRunning(boolean running) {
		this.running = running;
	}

	public void setWriting(boolean writing) {
		this.writing = writing;
	}


	public Map<String, List<FIFOReportDTO>> getPartId_data_map() {
		return partId_data_map;
	}

	
	
	@Override
	public void run() {
		try{
		System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Thread started%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
		Integer excelRowCounter = 9;																										
		Integer excelsummpartCounter = 10;
		ArrayList<SummaryParts> summaryParts = new ArrayList<SummaryParts>();
		ArrayList<SummaryInv> invs = new ArrayList<SummaryInv>();
		SummaryParts parts = new SummaryParts();
		SummaryInv inv = new SummaryInv();
		
		do{
			while(partId_data_map.size() > 0){
				String partId =  partId_data_map.keySet().iterator().next();
				List<FIFOReportDTO> finalReportList = partId_data_map.get(partId);
				//System.out.println("Processing part id: " + partId + " : size of finalReportList : " + finalReportList.size());
				
				//get data out of map for a key
				long closingQuantitySummary =0;
				double closingValueSummary =0.0d;
				FIFOReportDTO fifoReportDTO = null;
				Date previousTransactDate = null;
				long receiptSummaryQuantity = 0;
				double receiptSummaryValue = 0.0d;
				long consumptionSummaryQuantity = 0;
				double consumptionSummaryValue = 0.0d;
				if(finalReportList.size() == 0){
					partId_data_map.remove(partId);
					continue;
				}
				parts = new SummaryParts();
				parts.setPartId(partId.substring(0, partId.indexOf("####")));
				inv = new SummaryInv();
				
				for(int i=0;i < finalReportList.size();i++){
					fifoReportDTO = finalReportList.get(i);
					if(i==0){
						previousTransactDate = fifoReportDTO.getTransactionDate();
					}
					
					if((i+1) == finalReportList.size())
					{
						fifoReportDTO.printClosingStats = true;
						if(null != fifoReportDTO.getClosingQuantity())															
							closingQuantitySummary+=fifoReportDTO.getClosingQuantity();
						if(null != fifoReportDTO.getClosingValue())																
							closingValueSummary+=fifoReportDTO.getClosingValue();
					}
					else if(fifoReportDTO.getTransactionDate().compareTo(finalReportList.get(i+1).getTransactionDate()) !=0){
						fifoReportDTO.printClosingStats = true;
						
					}
					
					if(Receipt_Transaction_Type.contains(fifoReportDTO.getTransactionType())){
						if(fifoReportDTO.getQuantity() != null)
							receiptSummaryQuantity+=fifoReportDTO.getQuantity();
						if(fifoReportDTO.getValue() != null)
							receiptSummaryValue+=fifoReportDTO.getValue();
					}else if(Consumption_Transaction_Type.contains(fifoReportDTO.getTransactionType())){
						if(fifoReportDTO.getQuantity() != null)
							consumptionSummaryQuantity+=fifoReportDTO.getQuantity();
						if(fifoReportDTO.getValue() != null)
							consumptionSummaryValue+=fifoReportDTO.getValue();
					}
					
					if(reportGenerateForm.getReportType().equalsIgnoreCase("Summary-PartWise"))
					{
						
						parts.setClosingQuantity(closingQuantitySummary);
						parts.setClosingValue(closingValueSummary);
						parts.setClosingRate(closingQuantitySummary>0?closingValueSummary/closingQuantitySummary:0);
						parts.setPartId(fifoReportDTO.getPartId());
						parts.setPartDesc(fifoReportDTO.getPartDesc());
						parts.setInventoryType(fifoReportDTO.getInventoryType());
						ReportSerializerService.createSummaryPartWise(fifoReportDTO, parts);
						
					}
					else if(reportGenerateForm.getReportType().equalsIgnoreCase("Summary-InventoryTypeWise"))
					{
						inv.setClosingQuantity(closingQuantitySummary);
						inv.setClosingValue(closingValueSummary);
						inv.setClosingRate(closingQuantitySummary>0?closingValueSummary/closingQuantitySummary:0);
						inv.setInventoryType(fifoReportDTO.getInventoryType());
						ReportSerializerService.createSummaryPartWise(fifoReportDTO, inv);
					}
				}
				
				if(reportGenerateForm.getReportType().equalsIgnoreCase("Summary-PartWise"))
					summaryParts.add(parts);
				else if(reportGenerateForm.getReportType().equalsIgnoreCase("Summary-InventoryTypeWise"))
					addInv(inv,invs);
				
				// create excel
				if(reportGenerateForm.getReportType().equalsIgnoreCase("detailed")){
					try {
						excelRowCounter =  ExcelCreationService.appendDetailedSheet(excelRowCounter,workbook,finalReportList,reportGenerateForm,reportDate);
					} catch (Throwable e) {
						e.printStackTrace();
					}	
				}
				
				// remove entry from map for the above key
				partId_data_map.remove(partId);
				finalReportList.clear();
				finalReportList  = null;
			}
			Thread.sleep(500l);
			
		}while(running);
		
		if(reportGenerateForm.getReportType().equalsIgnoreCase("Summary-InventoryTypeWise"))
			ExcelCreationService.createInvSummary(invs,workbook, excelsummpartCounter,reportGenerateForm,reportDate);
		else if(reportGenerateForm.getReportType().equalsIgnoreCase("Summary-PartWise"))
			ExcelCreationService.createPartSummary(summaryParts,workbook, excelsummpartCounter,reportGenerateForm,reportDate);
			
		
		String pathName = null;
		
		if(reportGenerateForm.getReportCategory().equals("StockLedger")){
			pathName = ApplicationConstants.pathToExcel+ System.getProperty("file.separator") + reportGenerateForm.getValuationMethod() 
				+ System.getProperty("file.separator") + reportGenerateForm.getReportCategory() +  System.getProperty("file.separator") + reportGenerateForm.getReportType() 
				+ System.getProperty("file.separator") + simpleDateFormat.format(reportDate) + System.getProperty("file.separator");
		}
		else{
			pathName = ApplicationConstants.pathToExcel+ System.getProperty("file.separator") 
				+ simpleDateFormat.format(reportDate) + System.getProperty("file.separator");
		}
		String fileName = reportGenerateForm.getValuationMethod() + simpleDateFormat.format(reportGenerateForm.getStartDate()) 
				+ simpleDateFormat.format(reportGenerateForm.getEndDate()) + simpleDateFormat2.format(reportDate) +".xls";
		
		
		FileOutputStream fileOut = new FileOutputStream(pathName + fileName);
		workbook.write(fileOut);
		fileOut.flush();
		fileOut.close();
		}catch (Throwable e) {
			e.printStackTrace();
		}
		
	}

	private void addInv(SummaryInv inv,ArrayList<SummaryInv> invs)
	{
		if(invs.contains(inv))
			{
				SummaryInv inv2 = invs.get(invs.indexOf(inv));
				inv2.setCaptiveAmount(inv2.getCaptiveAmount()+inv.getCaptiveAmount());
				inv2.setCaptiveQuantity(inv2.getCaptiveQuantity()+inv.getCaptiveQuantity());
				inv2.setClosingQuantity(inv2.getClosingQuantity()+inv.getClosingQuantity());
				inv2.setClosingValue(inv2.getClosingValue()+inv.getClosingValue());
				inv2.setConsAmount(inv2.getConsAmount()+inv.getConsAmount());
				inv2.setConsQuantity(inv2.getConsQuantity()+inv.getConsQuantity());
				inv2.setCostPriceAmount(inv2.getCostPriceAmount()+inv.getCostPriceAmount());
				inv2.setCostPriceQuantity(inv2.getCostPriceQuantity()+inv.getCostPriceQuantity());
				inv2.setCustomAmount(inv2.getCustomAmount()+inv.getCustomAmount());
				inv2.setCustomQuantity(inv2.getCustomQuantity()+inv.getCustomQuantity());
				inv2.setFiAdjAmount(inv2.getFiAdjAmount()+inv.getFiAdjAmount());
				inv2.setFiAdjQuantity(inv2.getFiAdjQuantity()+inv.getFiAdjQuantity());
				inv2.setFocAmount(inv2.getFocAmount()+inv.getFocAmount());
				inv2.setFocQuantity(inv2.getFocQuantity()+inv.getFocQuantity());
				inv2.setForexAmount(inv2.getForexAmount()+inv.getForexAmount());
				inv2.setForexQuantity(inv2.getForexQuantity()+inv.getForexQuantity());
				inv2.setInvAdjAmount(inv2.getInvAdjAmount()+inv.getInvAdjAmount());
				inv2.setInvAdjQuantity(inv2.getInvAdjQuantity()+inv.getInvAdjQuantity());
				inv2.setOpeningAmount(inv2.getOpeningAmount()+inv.getOpeningAmount());
				inv2.setOpeningQuanitity(inv2.getOpeningQuanitity()+inv.getOpeningQuanitity());
				inv2.setOtherConsAmount(inv2.getOtherConsAmount()+inv.getOtherConsAmount());
				inv2.setOtherConsQuantity(inv2.getOtherConsQuantity()+inv.getOtherConsQuantity());
				inv2.setRetroAmount(inv2.getRetroAmount()+inv.getRetroAmount());
				inv2.setRetroQuantity(inv2.getRetroQuantity()+inv.getRetroQuantity());
				inv2.setRtvAmount(inv2.getRtvAmount()+inv.getRtvAmount());
				inv2.setRtvQuantity(inv2.getRtvQuantity()+inv.getRtvQuantity());
				inv2.setSalesAmount(inv2.getSalesAmount()+inv.getSalesAmount());
				inv2.setSalesQuantity(inv2.getSalesQuantity()+inv.getSalesQuantity());
				inv2.setScrapAmount(inv2.getScrapAmount()+inv.getScrapAmount());
				inv2.setScrapQuantity(inv2.getScrapQuantity()+inv.getScrapQuantity());
				inv2.setzGrirAmount(inv2.getzGrirAmount()+inv.getzGrirAmount());
				inv2.setzGrirQuantity(inv2.getzGrirQuantity()+inv.getzGrirQuantity());
				inv2.setClosingQuantity(inv2.getClosingQuantity()+inv.getClosingQuantity());
				inv2.setClosingValue(inv2.getClosingValue()+inv.getClosingValue());
							
			}
			else
				invs.add(inv);
	}
}
